今天我們將學習投資組合的概念,並實作一個簡單的多資產投資組合。投資組合能夠分散投資風險,通過將資金配置到不同資產類別中,降低單一資產波動對整體投資的影響。今日 Colab
投資組合是將資金配置於多種資產類別(如股票、債券、黃金、房地產、現金等)以達到分散風險並實現收益最大化的投資策略。多資產投資組合的核心是平衡風險和回報,確保在市場波動時仍然能夠維持相對穩定的收益。但需要注意分散投資的標的需要好好思考,如果都是同一類型可能沒有到分散的目的
我們將使用 Backtrader
來實作一個包含多種資產(例如蘋果股票 AAPL、谷歌股票 GOOGL 和黃金 ETF GLD)的簡單投資組合。
首先,我們將從 yfinance
下載所需的資產數據。
import backtrader as bt
import yfinance as yf
from datetime import datetime
# 下載多資產的數據
symbols = ['AAPL', 'GOOGL', 'GLD']
data_feeds = []
for symbol in symbols:
data = yf.download(symbol, start="2010-01-01", end="2020-01-01")
data_feed = bt.feeds.PandasData(dataname=data)
data_feeds.append(data_feed)
我們將創建一個簡單的策略,將資金平均分配到每個資產中。這裡我們使用 backtrader
的內建功能來實現這一策略:
class MultiAssetStrategy(bt.Strategy):
def __init__(self):
self.size = 0 # 用於保存每個資產的持倉量
def next(self):
# 在第一次運行時,根據現有現金分配資金
if self.size == 0:
cash = self.broker.getcash()
per_asset_cash = cash / len(self.datas) # 平均分配每個資產的資金
for data in self.datas:
size = int(per_asset_cash / data.close[0]) # 根據每個資產的價格計算要買入的數量
self.buy(data=data, size=size)
self.size += size # 更新持倉量
# 初始化 Cerebro 回測引擎
cerebro = bt.Cerebro()
cerebro.addstrategy(MultiAssetStrategy)
# 添加多個資產數據
for data_feed in data_feeds:
cerebro.adddata(data_feed)
# 設定初始資金
cerebro.broker.setcash(100000.0)
# 執行回測
print(f'初始資金: {cerebro.broker.getvalue():.2f}')
cerebro.run()
print(f'回測後資金: {cerebro.broker.getvalue():.2f}')
cerebro.plot(iplot=False)
在運行此策略後,我們可以看到資金隨著時間的變化,以及多資產投資組合的總體表現。接下來可以考慮進行以下優化:
我們與單一資產來做比較,如下程式,也可去 Colab 來直接執行:
# Re-import necessary libraries
import backtrader as bt
import yfinance as yf
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from datetime import datetime
# 下載多資產的數據
symbols = ['AAPL', 'GOOGL', 'GLD']
data_feeds = {}
for symbol in symbols:
data = yf.download(symbol, start="2010-01-01", end="2020-01-01")
data_feeds[symbol] = bt.feeds.PandasData(dataname=data)
# 建立多資產投資組合策略
class MultiAssetStrategy(bt.Strategy):
def __init__(self):
self.size = 0 # 用於保存每個資產的持倉量
self.daily_value = [] # 用於記錄每日投資組合價值
def next(self):
# 在第一次運行時,根據現有現金分配資金
if self.size == 0:
cash = self.broker.getcash()
per_asset_cash = cash / len(self.datas) # 平均分配每個資產的資金
for data in self.datas:
size = int(per_asset_cash / data.close[0]) # 根據每個資產的價格計算要買入的數量
self.buy(data=data, size=size)
self.size += size # 更新持倉量
self.daily_value.append(self.broker.getvalue()) # 記錄每日投資組合價值
# 建立單一資產投資策略
class SingleAssetStrategy(bt.Strategy):
def __init__(self):
self.size = 0 # 用於保存持倉量
self.daily_value = [] # 用於記錄每日投資組合價值
def next(self):
if self.size == 0:
cash = self.broker.getcash()
size = int(cash / self.datas[0].close[0])
self.buy(data=self.datas[0], size=size)
self.size += size
self.daily_value.append(self.broker.getvalue()) # 記錄每日投資組合價值
# 初始化 Cerebro 回測引擎
def run_strategy(strategy_class, data_feed):
cerebro = bt.Cerebro()
cerebro.addstrategy(strategy_class)
cerebro.adddata(data_feed)
cerebro.broker.setcash(100000.0)
result = cerebro.run()
return result[0].daily_value # 返回每日投資組合價值
# 執行多資產策略的回測,並記錄每日資產價值
multi_asset_values = run_strategy(MultiAssetStrategy, data_feeds['AAPL'])
for symbol in ['GOOGL', 'GLD']:
cerebro = bt.Cerebro()
cerebro.adddata(data_feeds[symbol])
cerebro.addstrategy(MultiAssetStrategy)
cerebro.broker.setcash(100000.0)
result = cerebro.run()
multi_asset_values = [x + y for x, y in zip(multi_asset_values, result[0].daily_value)]
multi_asset_values = [x / 3 for x in multi_asset_values] # 計算多資產每日的平均值
# 執行每一種單一資產策略的回測
single_asset_values = {}
for symbol in symbols:
single_asset_values[symbol] = run_strategy(SingleAssetStrategy, data_feeds[symbol])
# 計算波動率
def calculate_volatility(daily_values):
returns = pd.Series(daily_values).pct_change().dropna()
volatility = returns.std() * np.sqrt(252) # 年化波動率
return volatility
multi_asset_volatility = calculate_volatility(multi_asset_values)
single_asset_volatilities = {symbol: calculate_volatility(values) for symbol, values in single_asset_values.items()}
print("single_asset_volatilities",single_asset_volatilities)
# 視覺化結果
plt.figure(figsize=(14, 6))
# 資產最終價值比較
final_values = [multi_asset_values[-1]] + [single_asset_values[symbol][-1] for symbol in symbols]
plt.subplot(1, 2, 1)
plt.bar(['Multi-Asset'] + symbols, final_values, color=['blue', 'green', 'red', 'orange'])
plt.title('Final Portfolio Values')
plt.ylabel('Value ($)')
# 波動率比較
volatilities = [multi_asset_volatility] + [single_asset_volatilities[symbol] for symbol in symbols]
plt.subplot(1, 2, 2)
plt.bar(['Multi-Asset'] + symbols, volatilities, color=['blue', 'green', 'red', 'orange'])
plt.title('Portfolio Volatility')
plt.ylabel('Annualized Volatility')
plt.tight_layout()
plt.show()
可得下面結果:
可以看到多資產配置時獲益不錯且波動率不是最高,另外單一資產策略的波動率計算結果出現 0.0
可能有以下原因:
交易次數不足:對於 AAPL
和 GOOGL
,在回測期間,策略可能只有一次買入操作,之後沒有進行賣出或再次買入,導致每日資產價值沒有變化。因此,計算每日收益率時,收益率都是 0
,最終導致波動率也為 0.0
。
數據記錄問題:可能策略在執行過程中沒有正確記錄每日的組合價值,導致缺少資產價值變化的資訊。
價格問題:在所選的日期範圍內,某些股票的價格可能變動非常小或保持平穩(例如沒有足夠的歷史波動),因此計算出的波動率為 0.0
。
next
方法中正確記錄每日組合價值:檢查是否每一天都成功記錄了組合價值。為了確保計算波動率時數據的完整性,我們可以打印每個策略的每日組合價值,並檢查 AAPL
和 GOOGL
的波動情況:
# 打印每個策略的每日資產價值
print("Multi-Asset Strategy Final Values:", multi_asset_values)
for symbol in symbols:
print(f"Single Asset Strategy ({symbol}) Final Values:", single_asset_values[symbol])
今天我們學習了多資產投資組合的概念,並實作了一個簡單的投資組合策略。在現實投資中,多資產投資組合可以有效地分散風險,並提高投資組合的穩定性。
今日作業:
透過這些練習,你將能夠更加熟悉多資產投資組合的構建與管理,並學會如何在實踐中應用這些技巧,創建更有效的投資組合。